#include "FunctionContentBuilder.h"

#include "ScriptCompiler/ScriptFileContext.h"

#include "ScriptCompiler/AST/FunctionContentNode.h"

#include "ScriptCompiler/ASTBuilder/ExpressionBuilder.h"

#include "ScriptCompiler/ASTBuilder/SentenceBlockBuilder.h"

#include "ScriptCompiler/AST/ExpressionSentence.h"

CFunctionContentBuilder::CFunctionContentBuilder(std::shared_ptr<CScriptFileContext> InContext)
{
    Context = InContext;
    Result = std::make_shared<CFunctionContentNode>(Context);
}

bool CFunctionContentBuilder::ReadCurentToken()
{
    //read '{' or '=>'
    auto FirstToken = Context->GetCurrentToken();
    Result->FirstToken = FirstToken;

    if (FirstToken->Type == EScriptTokenType::LeftBrace)
    {   
        Result->IsLambda=false;
        Context->CurrentTokenIndex++;

        auto RightBraceIndex= FindPairedBrace(Context);

        if(!RightBraceIndex) 
        {
            //raise error
            Context->RaiseError(10152,FirstToken,U"cant find paired '}'");
            return false;
        }

        //read function body
        auto BlockBuilder = std::make_shared<CSentenceBlockBuilder>
            (Context,RightBraceIndex.GetValue());
        if (!BlockBuilder->ReadCurentToken())
        {
            return false;
        }
        Result->Content = BlockBuilder->Result;

        //skip right '}'
        assert(Context->GetCurrentToken()->Type==EScriptTokenType::RightBrace);
        Context->CurrentTokenIndex++;

        return true;
    }
    else if (FirstToken->Type == EScriptTokenType::LambdaOperator)
    {
        Result->IsLambda=true;
        
        Context->CurrentTokenIndex++;
        
        //find next ';'
        auto SemicolonIndex= FindNextToken(EScriptTokenType::Semicolon,Context);
        
        if(!SemicolonIndex)
        {
            //raise Error
            Context->RaiseError(10153,FirstToken,U"cant find ';'");
            return false;
        }

        //read function body
        auto ExpressionBuilder = std::make_shared<CExpressionBuilder>
            (Context,SemicolonIndex.GetValue());

        if (!ExpressionBuilder->ReadCurentToken())
        {
            return false;
        }

        Result->Content = std::make_shared<CSentenceBlockNode>(Context);
        Result->Content->Sentences.Add(
            std::make_shared<CExpressionSentence>(Context,ExpressionBuilder->Result));
        
        //skip ;
        assert(Context->GetCurrentToken()->Type==EScriptTokenType::Semicolon);
        Context->CurrentTokenIndex++;
        
        return true;
    }
    else
    {
        Context->RaiseError(10059,FirstToken,U"Expected '{' or '=>'");
        return false;
    }
    

}
